'use strict';
const util = require('util');
const path = require('path');
let projectPath = process.cwd();
let stackReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/i;
let stackReg2 = /at\s+()(.*):(\d*):(\d*)/i;
let formatRegExp = /%[sdjt]/g;
class Log {
    constructor() {
        this.replaceConsole();
    }
    setNodeName(nodeName) {
        this.nodeName = nodeName;
    }
    log(message) {
    }
    replaceConsole() {
        let self = this;
        let methods = ['log', 'trace', 'debug', 'info', 'warn', 'error'];
        methods.forEach(function (method, i) {
            self[method] = console[method];
            console[method] = function () {
                let message = self.logMain(arguments);
                self[methods[i]](message);
            };
        });
    }
    logMain(args) {
        let self = this, file, line, method, _path, pos, stack;
        let stacklist = (new Error()).stack.split('\n').slice(2);
        let s = stacklist[1], sp = stackReg.exec(s) || stackReg2.exec(s);
        if (sp && sp.length === 5) {
            method = sp[1];
            _path = sp[2].replace(projectPath, '');
            file = path.basename(sp[2]);
            line = sp[3];
            pos = sp[4];
            stack = stacklist.join('\n');
        }
        let msg = self.format.apply(self, args);
        if (this.nodeName) {
            return `${[this.nodeName]}${file}:${line} ${msg}`;
        }
        else {
            return `${file}:${line} ${msg}`;
        }
    }
    format(f) {
        let self = this;
        let inspectOpt = {
            showHidden: false,
            depth: 2
        };
        let args = arguments;
        let i = 0;
        if (typeof f !== 'string') {
            let objects = [];
            for (; i < args.length; i++) {
                objects.push(util.inspect(args[i], inspectOpt));
            }
            return objects.join();
        }
        i = 1;
        let str = String(f).replace(formatRegExp, function (x) {
            switch (x) {
                case '%s':
                    return String(args[i++]);
                case '%d':
                    return String(Number(args[i++]));
                case '%j':
                    try {
                        return JSON.stringify(args[i++]);
                    }
                    catch (e) {
                        return '[Circular]';
                    }
                case '%t':
                    return util.inspect(args[i++], inspectOpt);
                default:
                    return x;
            }
        });
        for (let len = args.length, x = args[i]; i < len; x = args[++i]) {
            if (x === null || typeof x !== 'object') {
                str += ' ' + x;
            }
            else {
                str += ' ' + util.inspect(x, inspectOpt);
            }
        }
        return str;
    }
}
exports.Log = Log;
exports.log = new Log();
